//
//  PhotoGridCell.swift
//  YCCamera
//
//  Created by Billy on 3/7/25.
//

import UIKit
import Photos

class PhotoGridCell: UICollectionViewCell {
    private let itemsPerRow: CGFloat = 3
    private let sectionInsets = UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 5)
    
    private lazy var collectionView: UICollectionView = {
        let layout = UICollectionViewFlowLayout()
        
        let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
        collectionView.backgroundColor = .black
        collectionView.delegate = self
        collectionView.dataSource = self
        collectionView.register(PhotoCell.self, forCellWithReuseIdentifier: "PhotoCell")
        return collectionView
    }()
    
    private var fetchResult: PHFetchResult<PHAsset>?
    private var imageManager: PHCachingImageManager?
    private var thumbnailSize: CGSize = .zero
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        setupUI()
                // 注册照片库变化观察者
        PHPhotoLibrary.shared().register(self)
    }
    
    deinit {
        // 移除照片库变化观察者
        PHPhotoLibrary.shared().unregisterChangeObserver(self)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    private func setupUI() {
        contentView.addSubview(collectionView)
        collectionView.snp.makeConstraints { make in
            make.edges.equalToSuperview()
        }
    }
    
    func configure(with fetchResult: PHFetchResult<PHAsset>, imageManager: PHCachingImageManager, thumbnailSize: CGSize) {
        self.fetchResult = fetchResult
        self.imageManager = imageManager
        self.thumbnailSize = thumbnailSize
        collectionView.reloadData()
    }
    
    func indexPathsForElements(in rect: CGRect) -> [IndexPath] {
        return collectionView.indexPathsForElements(in: rect)
    }
}

extension PhotoGridCell: UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return fetchResult?.count ?? 0
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "PhotoCell", for: indexPath) as! PhotoCell
        
        if let asset = fetchResult?.object(at: indexPath.item) {
            // 配置 LivePhoto 标识
            cell.configure(with: asset)
            
            let options = PHImageRequestOptions()
            // 先返回低质量的预览图，然后返回高质量的图像
            options.deliveryMode = .opportunistic
            // 是否允许从 iCloud 下载图片
            options.isNetworkAccessAllowed = true
            // 缩略图的质量(快速)
            options.resizeMode = .fast
            
            if let requestID = cell.requestID {
                imageManager?.cancelImageRequest(requestID)
                cell.requestID = nil
            }
            
            cell.representedAssetIdentifier = asset.localIdentifier
            cell.imageView.image = nil
            
            let requestID = imageManager?.requestImage(
                for: asset,
                targetSize: thumbnailSize,
                contentMode: .aspectFill,
                options: options
            ) { [weak cell] image, info in
                guard let cell = cell, cell.representedAssetIdentifier == asset.localIdentifier else { return }
                
                DispatchQueue.main.async {
                    cell.imageView.image = image
                    
                    if let isDegraded = info?[PHImageResultIsDegradedKey] as? Bool, isDegraded {
                        cell.imageView.alpha = 0.7
                        UIView.animate(withDuration: 0.3) {
                            cell.imageView.alpha = 1.0
                        }
                    }
                }
            }
            
            cell.requestID = requestID
        }
        
        return cell
    }
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        let paddingSpace = sectionInsets.left * (itemsPerRow + 1)
        let availableWidth = collectionView.bounds.width - paddingSpace
        let widthPerItem = availableWidth / itemsPerRow
        return CGSize(width: widthPerItem, height: widthPerItem)
    }
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
        return sectionInsets
    }
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
        return sectionInsets.left
    }
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
        return sectionInsets.left
    }
}

extension PhotoGridCell: UICollectionViewDelegate {
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        guard let fetchResult = fetchResult else { return }
        
        // 只收集当前可见缩略图的位置信息
        var visibleThumbnailFrames: [Int: CGRect] = [:]
        
        // 只处理可见的单元格
        for visibleCell in collectionView.visibleCells {
            guard let photoCell = visibleCell as? PhotoCell,
                  let visibleIndexPath = collectionView.indexPath(for: visibleCell) else { continue }
            
            // 将图片视图的边界转换为窗口坐标系
            let frame = photoCell.imageView.convert(photoCell.imageView.bounds, to: nil)
            visibleThumbnailFrames[visibleIndexPath.item] = frame
        }
        
        // 获取选中的 cell
        guard let selectedCell = collectionView.cellForItem(at: indexPath) as? PhotoCell else { return }
        
        // 创建并显示预览控制器，传入可见缩略图的位置信息
        let previewVC = YCPhotoPreviewViewController(
            fetchResult: fetchResult, 
            initialIndex: indexPath.item,
            thumbnailFrames: visibleThumbnailFrames
        )
        
        if let viewController = self.findViewController() {
            viewController.present(previewVC, animated: true)
        }
    }
}

// MARK: - PHPhotoLibraryChangeObserver
extension PhotoGridCell: PHPhotoLibraryChangeObserver {
    func photoLibraryDidChange(_ changeInstance: PHChange) {
        // 处理照片库变化
         // 确保在主线程更新 UI
        DispatchQueue.main.async { [weak self] in
            guard let self = self,
                  let fetchResult = self.fetchResult,
                  let changes = changeInstance.changeDetails(for: fetchResult) else {
                return
            }
            
            // 更新数据源
            self.fetchResult = changes.fetchResultAfterChanges
            
            // 判断是否需要完全重新加载
            let needsReloadData = changes.hasMoves || 
                                 (self.fetchResult?.count != changes.fetchResultBeforeChanges.count)
            
            if needsReloadData {
                // 重新加载全部数据
                self.collectionView.reloadData()
            } else if let changedIndexes = changes.changedIndexes, changedIndexes.count > 0 {
                // 仅更新已更改的单元格
                let changedIndexPaths = changedIndexes.map { IndexPath(item: $0, section: 0) }
                self.collectionView.reloadItems(at: changedIndexPaths)
            }
            // 如果有删除操作，更新缓存
            if let removedIndexes = changes.removedIndexes {
                let removedIndexPaths = removedIndexes.map { IndexPath(item: $0, section: 0) }
                self.imageManager?.stopCachingImagesForAllAssets()
                
                // 重新开始缓存可见区域的图片
                if let visibleIndexPaths = self.collectionView.indexPathsForVisibleItems as? [IndexPath] {
                    let visibleAssets = visibleIndexPaths.compactMap { indexPath -> PHAsset? in
                        guard indexPath.item < self.fetchResult?.count ?? 0 else { return nil }
                        return self.fetchResult?.object(at: indexPath.item)
                    }
                    self.imageManager?.startCachingImages(for: visibleAssets,
                                                        targetSize: self.thumbnailSize,
                                                        contentMode: .aspectFill,
                                                        options: nil)
                }
            }
        }
    }
}

private extension UIView {
    func findViewController() -> UIViewController? {
        if let nextResponder = self.next as? UIViewController {
            return nextResponder
        } else if let nextResponder = self.next as? UIView {
            return nextResponder.findViewController()
        } else {
            return nil
        }
    }
}

// MARK: - PhotoCell

class PhotoCell: UICollectionViewCell {
    
    let imageView: UIImageView = {
        let imageView = UIImageView()
        imageView.contentMode = .scaleAspectFill
        imageView.clipsToBounds = true
        return imageView
    }()
    
    let livePhotoIndicator: UIImageView = {
        let config = UIImage.SymbolConfiguration(pointSize: 18, weight: .medium)
        let image = UIImage(systemName: "livephoto", withConfiguration: config)
        let imageView = UIImageView(image: image)
        imageView.tintColor = .white
        imageView.contentMode = .scaleAspectFit
        imageView.isHidden = true
        return imageView
    }()
    
    var representedAssetIdentifier: String?
    var requestID: PHImageRequestID?
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        setupUI()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    private func setupUI() {
        self.layer.cornerRadius = 5
        self.clipsToBounds = true
        contentView.addSubview(imageView)
        imageView.snp.makeConstraints { make in
            make.edges.equalToSuperview()
        }
        
        contentView.addSubview(livePhotoIndicator)
        livePhotoIndicator.snp.makeConstraints { make in
            make.top.equalTo(5)
            make.right.equalTo(-5)
            make.width.height.equalTo(16)
        }
    }
    
    func configure(with asset: PHAsset) {
        // 显示或隐藏 LivePhoto 标识
        livePhotoIndicator.isHidden = !asset.mediaSubtypes.contains(.photoLive)
    }
    
    override func prepareForReuse() {
        super.prepareForReuse()
        imageView.image = nil
        livePhotoIndicator.isHidden = true
    }
}
